package com.qf.efserver.food.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qf.common.core.entity.Nutrition;
import com.qf.common.core.entity.Users;
import com.qf.common.core.utils.TokenUtils;
import com.qf.common.redis.utils.RedisUtils;
import com.qf.efserver.food.VO.RecommendFoodVO;
import com.qf.efserver.food.mapper.NutritionFoodMapper;
import com.qf.efserver.food.param.AddCustomizeNutritionParam;
import com.qf.efserver.food.param.UpdateCustomizeNutritionParam;
import com.qf.efserver.food.service.NutritionFoodService;
import com.qf.efserver.food.service.UserDefinedNutritionService;
import com.qf.efserver.user.personaldata.service.UsersService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * Author hehecheng
 * Date 2024/11/13
 * 祝我们都能遇见真诚的人
 * 见字如面
 */
@Service
public class NutritionFoodServiceImpl implements NutritionFoodService {

    @Resource
    private NutritionFoodMapper nutritionFoodMapper;

    @Resource
    private UsersService usersService;

    @Resource
    private UserDefinedNutritionService userDefinedNutritionService;

    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 推荐食物
     *
     * @return
     */
    @Override
    public List<RecommendFoodVO> recommendedFood() {
        Integer uid = TokenUtils.getUidFromToken();
        Users users = usersService.getUserInfo();
        String mMdd = LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd"));
        String key = String.format("recommend:food:%s:%s", uid, mMdd);
        Object value = RedisUtils.getValue(key);
        if (value == null) {
            // 体重指数
            Double BMI = users.getWeight() / Math.pow(users.getHeight() / 100, 2);
            List<Nutrition> recommendFood = new ArrayList<>();
            Page<Nutrition> page = new Page<>(1, 5);
            // TODO sql查询太多
            if (BMI <= 18.4) {  // 偏低
                //高热量的食物：100克食物中含有超过250卡路里
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .ge("calories", 250)).getRecords());
                //高蛋白的食物：含有每100克食物中至少20克以上的蛋白质
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .ge("protein", 20)).getRecords());
                //碳水化合物丰富的食物：每100克食物中碳水化合物的含量超过15克常被认为是碳水化合物丰富的食物
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .ge("carbs", 15)).getRecords());
            } else if (BMI <= 23.9) {  // 标准
                // 均衡饮食：包含各类食品的组合，如瘦肉、鱼、蛋、果蔬和全谷物。
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .ge("calories", 50).lt("calories", 250)).getRecords());

            } else if (BMI <= 27.9) {  // 超重
                // 低热量高纤维的食物：绿色蔬菜、全谷类食品（如燕麦）、豆类。 每100克食物的热量通常低于50卡路里
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .lt("calories", 50)).getRecords());
                //高蛋白食物：瘦肉、鱼、蛋白粉。
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .lt("calories", 50)
                        .ge("protein", 20)).getRecords());
            } else {
                // 肥胖
                //低热量饮食：水果（如苹果、橙子）、非淀粉类蔬菜（如西兰花、胡萝卜）。每100克食物的热量通常低于50卡路里
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .lt("calories", 50)).getRecords());
                //高纤维食物：豆类、全谷物。
                recommendFood.addAll(nutritionFoodMapper.selectPage(page, new QueryWrapper<Nutrition>()
                        .lt("calories", 50).eq("food_type", 4)).getRecords());
            }
            List<RecommendFoodVO> foodVOS = recommendFood.stream().map(item -> {
                RecommendFoodVO recommendFoodVO = new RecommendFoodVO();
                BeanUtils.copyProperties(item, recommendFoodVO);
                return recommendFoodVO;
            }).collect(Collectors.toList());
            RedisUtils.setValue(key, foodVOS);
            return foodVOS;
        } else {
            List<RecommendFoodVO> recommendFoodVOS = (List<RecommendFoodVO>) value;
            return recommendFoodVOS;
        }
    }

    /**
     * 最近推荐的食物
     *
     * @return
     */
    @Override
    public List<RecommendFoodVO> recentFood() {
        Integer uid = TokenUtils.getUidFromToken();
        String key = null;
        // 获取用户昨天的食物推荐
        String mMdd = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("MMdd"));
        key = String.format("recommend:food:%s:%s", uid, mMdd);
        List<RecommendFoodVO> recentFood = null;
        Object value = RedisUtils.getValue(key);
        if (value == null) {
            // 如果昨天没有推荐，则使用今天的
            key = String.format("recommend:food:%s:%s", uid, LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd")));
            recentFood = (List<RecommendFoodVO>) RedisUtils.getValue(key);
        } else {
            recentFood = (List<RecommendFoodVO>) value;
        }
        return recentFood;
    }

    @Override
    public Integer addCustomNutrition(AddCustomizeNutritionParam addCustomizeNutritionParam) {
        Integer uid = TokenUtils.getUidFromToken();
        Nutrition nutrition = new Nutrition();
        nutrition.setFoodType(6);
        BeanUtils.copyProperties(addCustomizeNutritionParam, nutrition);
        nutritionFoodMapper.insert(nutrition);
        // 存入redis
        threadPoolExecutor.execute(() -> {
            String key = String.format("custom:food:%s", uid);
            RedisUtils.hashPut(key, nutrition.getFoodId().toString(), nutrition);
        });
        return nutrition.getFoodId();
    }

    /**
     * 获取用户自定义的食物
     *
     * @return
     */
    @Override
    public List<RecommendFoodVO> getUserCustomizeNutrition() {
        Integer uid = TokenUtils.getUidFromToken();
        List<RecommendFoodVO> list = nutritionFoodMapper.selectUserCustomizeNutrition(uid);
        return list;
    }

    @Override
    public void updateUserCustomizeNutrition(UpdateCustomizeNutritionParam updateCustomizeNutritionParam) {
        Integer uid = TokenUtils.getUidFromToken();
        Nutrition nutrition = new Nutrition();
        BeanUtils.copyProperties(updateCustomizeNutritionParam, nutrition);
        // 对数据库进行修改
        nutritionFoodMapper.update(nutrition, new LambdaUpdateWrapper<Nutrition>()
                .eq(Nutrition::getFoodId, nutrition.getFoodId()));
        String key = String.format("custom:food:%s", uid);
        RedisUtils.delKey(key);
    }

    /**
     * 用户删除自定义食物
     *
     * @param foodId
     */
    @Override
    public void delUserCustomizeNutrition(Integer foodId) {
        Integer uid = TokenUtils.getUidFromToken();
        nutritionFoodMapper.deleteById(foodId);
        threadPoolExecutor.execute(() -> {
            userDefinedNutritionService.delUserDefinedNutrition(uid, foodId);
        });

    }

    @Override
    public Nutrition selectById(Integer foodId) {
        return nutritionFoodMapper.selectById(foodId);
    }
}
